# coding=utf-8
import datetime

import jwt
import requests

from common.db import *
from common.utils import Utils
utils = Utils()
from api.common_api import Common_Api

# BPM外部接口固定认证字符串
MysoftJWT = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1IjoiIiwiYyI6ImFkbWluIiwicCI6IiJ9.14cRZTKTeOD23rhGFMh-w4g6lfU6b0FgqP6snpEPVA0'

class Bpm_Outside_Api(Common_Api):

    def get_process_instance_info(self,body):
        """
        通过业务ID 获取流程,流程名称,业务对象ID,业务对象名称
        :param body: {"businessGuid": "348d66aa-3658-41db-b563-af0b515e8af4"}
        :return:
        """
        url = '/api/flowinstance/approval/get-process-instance-info'
        resp = self.send(url, payload=body, method='post', headers={"Content-Type": "application/json", "MysoftJWT":MysoftJWT})
        return resp

    def get_process_state(self,body):
        """
        获取流程状态
        :param body: {"proc_id":"9576237a-d546-fa1d-8814-39ffb7dabdaf","user_guid":"",businessGuid: 4d3b3700-91e9-4731-a2c3-d35a507a8bf8}
        :return:
        """
        url = '/api/flowinstance/approval/get-process-state'
        resp = self.send(url, payload=body, method='post',
                         headers={"Content-Type": "application/json", "MysoftJWT": MysoftJWT})
        return resp

    def get_process_node_data_control(self,body):
        """
        获取任务对应权限设置
        :param body: {"proc_id":"9576237a-d546-fa1d-8814-39ffb7dabdaf","user_guid":"",businessGuid: 4d3b3700-91e9-4731-a2c3-d35a507a8bf8}
        :return:
        """
        url = '/api/flowinstance/approval/get-process-node-data-control'
        resp = self.send(url, payload=body, method='post',
                         headers={"Content-Type": "application/json", "MysoftJWT": MysoftJWT})
        return resp

    def get_by_ids(self,body):
        """
        根据用户id获取用户信息
        :param body: ["4230BC6E-69E6-46A9-A39E-B929A06A84E8","07082D55-0C04-4A90-80ED-08D838E35E7D"]
        :return:
        """
        url = '/api/resource/user/get-by-ids'
        resp = self.send(url, payload=body, method='post',
                         headers={"Content-Type": "application/json", "MysoftJWT": MysoftJWT})
        return resp

    def data_storage_save(self,body):
        """
        保存表单数据接口
        :param body:
        :return:
        """
        url = 'api/flowdefine/data-storage/save'
        resp = self.send(url, payload=body, method='post',
                         headers={"Content-Type": "application/json", "MysoftJWT": MysoftJWT})
        return resp

    def trigger_flow_event(self,user='',EventName='',HandleType='',BussinessGUID='',OtherParams='',body=''):
        """
        触发业务事件
        :param user: 用户code
        :param EventName: 事件名称
        :param HandleType: 处理类型
        :param BussinessGUID: 业务GUID
        :param OtherParams:
        :param body:
        :return:
        """
        """
        handle_type:
        Initiate	发起
        ReInitiate	重新发起
        Reject	终止
        Cancel	作废
        InitiateWithdraw	发起撤回
        RollbackToInitiate	驳回到发起
        Approve	审批
        AfterArchivedInvalid	归档后作废
        AfterDeleteDraft	删除草稿后事件
        
        event_name:
        before_start	发起审批前
        after_start	发起审批后
        before_terminate	终止前
        after_terminate	终止后
        before_invalid	作废前
        after_invalid	作废后
        before_archiving	归档前
        after_archiving	归档后
        before_reject	驳回前
        after_reject	驳回后
        before_withdraw	撤回前
        after_withdraw	撤回后
        before_attachments	同步附件
        before_relation	同步相关流程
        """
        # 通过请求获取用户组织信息
        user_orgs = self.get_users_by_name(user)
        # 用户基本信息
        user_base_info = self.jsonpath_value(user_orgs.json(), '$.data.data[0]')
        user_name = user_base_info['name']
        user_guid = user_base_info['id']
        if body == "":
            # 查询流程实例相关信息
            sql = f"""SELECT pe.id 'ProccessInstanceID',pe.PackageId,pe.BusinessKey 'BussinessGUID',pe.ProcessName,* FROM dbo.WfProcessInstance pe WITH (NOLOCK)
                            WHERE BusinessKey='{BussinessGUID}';"""
            result = sqlserver_query_return_contain_field(sql)  # 执行sql
            # 获取sql返回的数据，对应的字段信息
            ProccessInstanceID = utils.get_column_value_by_two_array(result, 'ProccessInstanceID')[0]
            ProcessName = utils.get_column_value_by_two_array(result, 'ProcessName')[0]
            PackageId = utils.get_column_value_by_two_array(result, 'PackageId')[0]
            # 标准入参
            body = {
                "EventName":EventName,
                "PackageID":PackageId,
                "UserID":user_guid,
                "StepEventConf":None,
                "BussinessKey":BussinessGUID,
                "HandleType":HandleType,
                "ProccessInstanceID":ProccessInstanceID,
                "ProcessName":ProcessName,
                "AuditorID":user_guid,
                "AuditorName":user_name,
                "FormData":{
                    "main":{
                    },
                    "children":{
                    }
                },
                "ManualExecution":False,
                "Opinion":"审批同意"
            }
        # 更新其他参数
        if OtherParams =='' or OtherParams ==None:
            OtherParams = {}
        body.update(OtherParams)
        url = '/api/flowdefine/flow-event/trigger-flow-event'
        resp = self.send(url, payload=body, method='post',
                         headers={"Content-Type": "application/json", "MysoftJWT": MysoftJWT})
        return resp

    def get_process_instance_steps_view(self,body):
        """
        获取流程步骤审批记录
        :param body:
        :return:
        """
        url = '/api/flowinstance/approval/get-process-instance-steps-view'
        resp = self.send(url, payload=body, method='post',
                         headers={"Content-Type": "application/json", "MysoftJWT": MysoftJWT})
        return resp

    def approval_invalid(self,user, BussinessGUID='', OtherParams='', body=''):
        """
        流程中心作废流程接口
        :param body:
        :return:
        """
        # 通过请求获取用户组织信息
        user_orgs = self.get_users_by_name(user)
        user_default = self.jsonpath_value(user_orgs.json(),
                                           '$.data.data[0].org_settings[?(@.is_default=="1" or @.is_default==1)]')
        org_id = user_default['org_id']
        name_path = user_default['name_path']
        Logger.info(f'用户【{user}】默认组织：【{name_path}】，对应组织GUID：【{org_id}】')
        # 用户基本信息
        user_base_info = self.jsonpath_value(user_orgs.json(), '$.data.data[0]')
        user_name = user_base_info['name']
        user_guid = user_base_info['id']
        if body == "":
            # 查询流程实例相关信息
            sql = f"""SELECT spe.ActivityOrder '序号', spe.ActivityName '步骤名称', ne.OrderCode '节点序号', ne.AssignedToUserName '责任人', ne.TaskState '节点状态', spe.ActivityState '步骤状态', pe.ProcessState '流程状态', u.code '用户code',pe.Id 'ProcessGUID',ne.Id 'NodeGUID'    
                FROM dbo.WfProcessInstance pe With (NoLock) JOIN dbo.WfTasks ne With (NoLock) ON pe.Id = ne.ProcessInstanceID 
                LEFT JOIN dbo.p_user u With (NoLock) ON u.id =ne.AssignedToUserID 
                JOIN WfActivityInstance spe With (NoLock) ON spe.ProcessInstanceID = ne.ProcessInstanceID AND ne.ActivityInstanceID=spe.Id
                WHERE pe.BusinessKey = '{BussinessGUID}' AND spe.ActivityState IN ('1','2') ORDER BY spe.ActivityOrder,ne.OrderCode;"""
            if jsonpath.jsonpath(OtherParams,'$.proc_id'):
                proc_id = jsonpath.jsonpath(OtherParams,'$.proc_id')[0]
                node_id = jsonpath.jsonpath(OtherParams,'$.node_id')[0]
            else:
                result = sqlserver_query_return_contain_field(sql)  # 执行sql
                # 获取sql返回的数据，对应的字段信息
                proc_id = utils.get_column_value_by_two_array(result, 'ProcessGUID')[0]
                node_id = utils.get_column_value_by_two_array(result, 'NodeGUID')[0]
            # 标准请求体
            body = {
                "proc_id":proc_id,
                "business_id":BussinessGUID,
                "node_id":node_id,
                "initiater":{
                    "initiater_org_id":org_id,
                    "initiater_org_name":name_path,
                    "initiater_id":user_guid,
                    "initiater_name":user_name
                },
                "form_data":{
                    "main": {
                        "id": None,
                        "instance_id": proc_id,
                        "business_id": BussinessGUID,
                        "name": "引擎名称",
                        "code": "引擎编码",
                        "started_by": "4230BC6E-69E6-46A9-A39E-B929A06A84E8",
                        "started_org": "11B11DB4-E907-4F1F-8835-B9DAAB6E1F23"
                    },
                    "children": {
                    }
                },
                "opinion":"接口作废流程",
                "step_cc_list":[]
            }
        # 更新其他参数
        if OtherParams =='' or OtherParams ==None:
            OtherParams = {}
        body.update(OtherParams)
        url = '/api/flowinstance/approval/invalid'
        resp = self.send(url, payload=body, method='post',
                         headers={"Content-Type": "application/json", "MysoftJWT": MysoftJWT})
        return resp

    def cancel_process(self,body):
        """
        归档流程作废(业务系统接口作废)
        :param body: {"businessGuid":"业务guid","reason":"作废原因"}
        """
        url = "/api/flowinstance/approval/cancel-process"
        resp = self.send(url, payload=body, method='post', headers={"Content-Type": "application/json", "MysoftJWT": MysoftJWT})
        return resp

    def get_verify_token(self, user, params):
        """
        获取verify_token
        :param user: usercode
        :param params: app_id=业务系统id，传入json
        :return:
        """
        key = "5f4f447e096953172220591473003525"
        user_orgs = self.get_users_by_name(user)
        # 用户基本信息
        user_base_info = self.jsonpath_value(user_orgs.json(), '$.data.data[0]')
        user_guid = user_base_info['id']
        url = self.host+'/api/third-party-auth/get-verify-token'
        jwt_token = self.GenerateJwtToken(key,user_guid,user)
        resp = requests.post(url,params=params,headers={"Content-Type": "application/json", "Mysoft.JWT": jwt_token})
        # url = '/api/third-party-auth/get-verify-token'
        # resp = self.send(url,method='post',
        #                  headers={"Content-Type": "application/json", "MysoftJWT": MysoftJWT})
        return resp

    def access_token(self,user,params):
        """
        第三方服务授权，获取access_token，目前只执行获取admin的用户token
        :param user: usercode，body是AES加密的用户code，目前只执行获取admin的用户token
        :param params: app_id=业务系统id，传入json
        :return:
        """
        key = "5f4f447e096953172220591473003525"
        data = "hvUY8fVq6o//Rr7eJAOGOZT3kqxn9ozjWz0g4PyFRWE="   #ASC加密后的用户信息
        user_orgs = self.get_users_by_name(user)
        # 用户基本信息
        user_base_info = self.jsonpath_value(user_orgs.json(), '$.data.data[0]')
        user_guid = user_base_info['id']
        url = self.host + '/api/third-party-auth/get-token'
        jwt_token = self.GenerateJwtToken(key, user_guid, user)
        resp = requests.post(url, params=params, data=data,
                             headers={"Content-Type": "application/json", "Mysoft.JWT": jwt_token})
        return resp

    def outside_save_draft(self,payload):
        """
        流程保存为草稿
        :param payload: 接口入参
        :return:
        """
        # 保存草稿
        url = self.host + '/api/flowinstance/process/save-draft'
        resp = requests.post(url, json=payload,
                             headers={"Content-Type": "application/json", "MysoftJWT": MysoftJWT})
        return resp

    def GenerateJwtToken(self,key,user_guid,user_code):
        """
        生成第三方授权的jwt token
        :param key: 流程中心后台-应用管理-编辑授权信息的JWT KEY字段
        :param user_guid:   用户id
        :param user_code:   用户code
        :return:
        """
        # user_guid = "4230BC6E-69E6-46A9-A39E-B929A06A84E8"
        # user_code = "admin"
        # key = "5f4f447e096953172220591473003525"
        now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        now_add = (datetime.datetime.now() + datetime.timedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S')  #加1天
        paload = {"u": user_guid,
                  "c": user_code,
                  "p": "",
                  "iat": now,
                  "nbf": now_add}
        token = jwt.encode(paload, key, "HS256")
        return token

